package com.meme.editor.gui.sprite2d;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.SystemColor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Point;
import java.awt.Container;

import javax.swing.AbstractAction;
import javax.swing.Icon;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;

import javax.swing.JViewport;

import org.apache.log4j.Logger;

import com.meme.app.AppRegistry;
import com.meme.editor.EntityObject;
import com.meme.editor.event.EntityChangedEvent;
import com.meme.editor.event.EntityObjectListener;
import com.meme.editor.gui.EntityChildrenListView;
import com.meme.editor.gui.PropertyEditPanel;
import com.meme.editor.model.sprite2d.PureModule;
import com.meme.editor.model.sprite2d.Module;
import com.meme.editor.model.sprite2d.PureModuleGroup;
import com.meme.editor.model.sprite2d.ModuleImage;
import com.meme.editor.model.sprite2d.ModuleGroup;
import com.meme.editor.model.sprite2d.ModuleRef;

import java.awt.event.ActionEvent;
import java.awt.event.MouseListener;


	
class ModuleGroupView_Icons extends JPanel
	implements EntityObjectListener, AncestorListener, MouseListener
{
	static Logger logger = Logger.getLogger (ModuleGroupView_Icons.class);
	
	//ImageModuleGroup mImageModuleGroup;
	ModuleGroup mModuleGroup;
	Rectangle[]   mModuleRegions;
	boolean mRegionsNeedUpdated;
	
	Module     mSelectedModule;
	
	int mModuleMargin = 5;
	int mCavasWidth;
	int mCavasHeight;
	
	public ModuleGroupView_Icons (ModuleGroup moduleGroup)
	{
		mModuleGroup = moduleGroup;
			
		//updateModuleRegions ();
		mRegionsNeedUpdated = true;

		addAncestorListener (this);
		addMouseListener (this);
	}
	
	@Override
	public void paintComponent (Graphics g)
	{
		drawModuleGroup (g);
	}	
	
	protected void drawModuleGroup (Graphics _g)
	{
		Graphics2D g = (Graphics2D)_g;
		logger.assertLog(getParent () instanceof JViewport, "parent should a JScrollPane");
		
		JViewport viewport = (JViewport) getParent ();
		Rectangle viewrect = viewport.getViewRect ();
		
		g.setColor (SystemColor.window);
		g.fillRect(viewrect.x, viewrect.y, viewrect.width, viewrect.height);
		
		int oldCamvasWidth = mCavasWidth;
		int oldCamvasHeight = mCavasHeight;
		
		mCavasHeight = viewrect.height;
		
		boolean drawIcon;
		boolean drawFrame = true;
		
		if ( mModuleGroup.isValid() )
			drawIcon = true;
		else
			drawIcon = false;

		
		Color color1 = new Color (255, 200, 200);
		Color color2 = new Color (200, 255, 200);
		Color color3 = new Color (128, 128, 200);
		
		int x = 0;//mCanvasMargin + mModuleMargin;
		int y = 0;//mCanvasMargin + mModuleMargin;
		
		if ( mRegionsNeedUpdated )
		{
			if ( mModuleRegions == null || mModuleRegions.length != mModuleGroup.getChildrenCount() )
				mModuleRegions = new Rectangle [mModuleGroup.getChildrenCount()];
		}
		
		FontMetrics fm = g.getFontMetrics();
		int strHeight = fm.getHeight();

		for (int i = 0; i < mModuleGroup.getChildrenCount(); ++ i)
		{
			Module module = (Module) mModuleGroup.getChildByIndex (i);
			
			int w = module.getWidth();
			int h = module.getHeight();
			int minx = module.getMinX();
			int miny = module.getMinY();
			
			String idStr = "" + module.getIndex();
			String nameStr = module.getName();
		
			int idStrWidth = fm.stringWidth(idStr);
			int nameStrWidth = fm.stringWidth(nameStr);
			int cellWidth = idStrWidth > nameStrWidth ? idStrWidth : nameStrWidth;
			if ( cellWidth < w ) cellWidth = w;
			cellWidth += mModuleMargin + mModuleMargin;
			
			int right = x + cellWidth;			

			if ( mModuleRegions [i] == null )
				mModuleRegions [i] = new Rectangle ();
			mModuleRegions [i].x = x;
			mModuleRegions [i].width = cellWidth;
			
			if ( right > viewrect.x && x < viewrect.x + viewrect.width )
			{
				if ( mSelectedModule == module )
					g.setColor ( color3 );
				else
					g.setColor ( color2);
				
				g.fillRect(x, viewrect.y, right - x, viewrect.height);
				
				if ( drawIcon )
					module.render(g, x + (cellWidth - w) / 2 - minx, y + ( mCavasHeight - h ) / 2 - miny, false, false, 1, 0 );
				
				if ( drawFrame )
				{
					g.setColor (Color.green);
					g.drawRect(x + (cellWidth - w) / 2, y + ( mCavasHeight - h ) / 2, w, h);
				}
				
				// draw id & name
				g.setColor(color1);
				g.fillRect (x, 0, cellWidth, strHeight);
				g.fillRect (x, mCavasHeight - strHeight, cellWidth, strHeight);
				g.setColor(Color.black);
				g.drawString(idStr, x + (cellWidth - idStrWidth) / 2, fm.getAscent());
				g.drawString(nameStr, x + (cellWidth - nameStrWidth) / 2, mCavasHeight - fm.getDescent() - 1);
				
				// lines
				g.drawLine (x, 0, x, mCavasHeight);
				g.drawLine (right, 0, right, mCavasHeight);
				g.drawLine (x, strHeight, right, strHeight);
				g.drawLine (x, mCavasHeight - strHeight, right, mCavasHeight - strHeight);
			}
			
			x = right;
		}
		
		mCavasWidth = x;

		if ( oldCamvasWidth != mCavasWidth || oldCamvasHeight != mCavasHeight )
		{
			mCavasWidth = x;
			setPreferredSize (new Dimension (mCavasWidth, mCavasHeight));
			revalidate(); // notify parent scroll panel to update
			repaint ();
		}
	}
	

	//AncestorListener, 
	@Override
	public void ancestorAdded(AncestorEvent event) 
	{
		mModuleGroup.addEntityObjectListener (this);

	}

	@Override
	public void ancestorRemoved(AncestorEvent event)  
	{
		mModuleGroup.removeEntityObjectListener (this);	
	}
	
	@Override
	public void ancestorMoved(AncestorEvent event) 
	{
		
	}

	// PropertyManagerListener
	@Override 
	public void notifyEntityChanged (EntityChangedEvent event) 
	{ 		
		repaint ();
	}
	
	
	void changeSelectedModule (Point p)
	{
		int i;
		for ( i = 0; i < mModuleRegions.length; ++ i )
		{
			//if ( mModuleRegions [i].contains( e.getPoint() ) )
			if ( mModuleRegions [i].x <= p.x 
					&& mModuleRegions [i].x + mModuleRegions [i].width > p.x )	
				break;
		}
		
		mSelectedModule = null;
		if ( i < mModuleRegions.length )
			mSelectedModule = (Module) ( mModuleGroup.getChildByIndex(i) );
		
		repaint ();
	}
	
	//MouseListener
	@Override 
	public void mouseClicked(java.awt.event.MouseEvent e)
	{
	}
	  
	@Override 
	public void mousePressed(java.awt.event.MouseEvent arg0)
	{
		
	}
		  
	@Override 
	public void mouseReleased(java.awt.event.MouseEvent e)
	{
		changeSelectedModule (e.getPoint());

		if (e.getButton () == e.BUTTON3 && mSelectedModule != null)
		{
			JPopupMenu popMenu = new JPopupMenu();
			AbstractAction action = new ReplaceModuleInPartAction (); 
			popMenu.add ( action );
			

			ModuleRef part = SharedData.sSelectedModuleRef;
			
			action.setEnabled(part != null && part.checkReferability(mSelectedModule));
			
			popMenu.show(this, e.getX(), e.getY());
		}
	}
		  
	@Override 
	public void mouseEntered(java.awt.event.MouseEvent arg0)
	{
		
	}
		  
	@Override 
	public void mouseExited(java.awt.event.MouseEvent arg0)
	{
		
	}
	
	class ReplaceModuleInPartAction extends AbstractAction 
	{
		public ReplaceModuleInPartAction ()
		{
			super ("Replaced by This One");
		}
		
	    public void actionPerformed(ActionEvent e) 
	    {
	    	ModuleRef part = SharedData.sSelectedModuleRef;
			part.setModule (mSelectedModule);
			part.commitModifications();
	    }
	}
}
